function myVue(option) {

  console.log('option',option)
  this.data = option.data;    // {text:"..."}

  // 遍历每一个属性，建立发布-订阅模式
  observe(this.data, this);    // {text:"..."},Vue实例

  // 遍历每一个dom节点，初始化每一个观察者
  var id = option.el;     // "app"
  var dom = nodeToFragment(document.getElementById(id), this);    // "#app",Vue实例

  // 编译完成后,dom返回到app
  document.getElementById(id).appendChild(dom)    // 更新dom节点
}

function observe(obj, vm) { // data对象 {text:"..."}, Vue实例
  // 遍历每一个属性，调用defineReactive方法
  Object.keys(obj).forEach(function (key) {
      defineReactive(vm, key, obj[key]);  // Vue实例,属性名 text, 属性值 "hello world"
  });
}

function defineReactive(obj, key, val) {    // Vue实例, 属性名 text, 属性值 "hello world"
  var dep = new Dep();// 一个属性对应的观察者数组，对应当前属性文档中所有需要响应的节点

  console.log(key,dep)
  // 重写getter和setter
  Object.defineProperty(obj, key, {
      get: function () {
          console.log('Dep.target',Dep.target) // Watcher
          if (Dep.target) dep.addSub(Dep.target); // Dep.target属性用于当实例化Watcher并初始化dom节点时，收集该观察者
          console.log(11111,dep)
          return val
      },
      set: function (newVal) {
          if (newVal === val) return
          val = newVal;
          // 属性值每次更新时发布通知
          dep.notify();
      }
  })
}

function Dep() {
  this.subs = []; // 用于存储每一个观察者
}

Dep.prototype = {
  // 添加观察者
  addSub: function (sub) {
      this.subs.push(sub);
  },
  // 发布，通知每一个观察者
  notify: function () {
      this.subs.forEach(function (sub) {
          sub.update();   // 即调用每个Watcher的update方法来达到更新视图的目的
      })
  }
}

function nodeToFragment(node, vm) { // vue实例绑定的dom节点 "#app", Vue实例
  var flag = document.createDocumentFragment(); // 创建一个新的空白的文档片段作为容器
  var child;

  console.log('node',node)

  while (child = node.firstChild) {   // while遍历每一个子节点
      complie(child, vm); // 编译子节点
      flag.appendChild(child);    // appendChild 从原父节点移除该子节点后再添加到容器下
  }

  return flag
}

function complie(node, vm) {    // 节点, Vue实例
  // 节点类型为元素
  if (node.nodeType === 1) {
      var attr = node.attributes; // 获取元素节点所有属性
      for (var i = 0; i < attr.length; i++) {
          if (attr[i].nodeName === 'v-model') { // 匹配到'v-model'
              var name = attr[i].nodeValue;   // 获取'v-model'绑定的属性名text
              node.addEventListener('input', function (e) { // 绑定input事件
                  // 给相应的data属性赋值，进而触发该属性的setter，进行发布
                  vm[name] = e.target.value;
              })
              node.value = vm.data[name]; // 初始化元素节点 input 的值
              node.removeAttribute('v-model') // 移除input的v-model属性
          }
      }
      return
  }
  var reg = /\{\{(.*)\}\}/    // 定义正则，用于匹配 {{...}}
  // 节点类型为文本
  if (node.nodeType === 3) {
      var str = node.nodeValue.trim(); // 删除字符串的头尾空白符
      if (reg.test(str)) {
          var name = RegExp.$1;   // 属性名 text
          // 重置节点内容并添加依赖 
          new Watcher(vm, node, name);    // 实例化观察者对象，传入（Vue实例, 文本节点, 属性名text）
      }
      return
  }
}


function Watcher(vm, node, name) {  // Vue实例,文本节点,text
  Dep.target = this;  // Watcher  / 在这里设置 get的时候 Dep对象上有这个属性 
  this.name = name;   // 属性名
  this.node = node;   // 节点
  this.vm = vm;       // Vue实例
  this.update();      // 初始化文本节点的nodeValue
  Dep.target = null;  // 初始化之后销毁
}

Watcher.prototype = {
  // 更新当前节点视图
  update: function () {
      console.log(11111111)
      this.get();
      console.log(222222222)
      console.log('nosww',this.node)
      this.node.nodeValue = this.value;
  },
  // 获取vue实例data对象相应的属性值
  get: function () {
      this.value = this.vm[this.name]; // this.vm[this.name]会触发第四步定义的getter，当Dep.target存在时就会收集观察者
  }
}